package com.zackeus.xupdate.widget;

import android.Manifest;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.Window;
import android.view.WindowManager;

import androidx.annotation.CallSuper;
import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import com.elvishew.xlog.XLog;
import com.zackeus.common.utils.FileUtils;
import com.zackeus.common.utils.Utils;
import com.zackeus.xupdate.XUpdate;
import com.zackeus.xupdate.XUpdateService;
import com.zackeus.xupdate.constant.Error;
import com.zackeus.xupdate.entity.LibraryPromptEntity;
import com.zackeus.xupdate.entity.LibraryUpdateEntity;
import com.zackeus.xupdate.entity.PromptEntity;
import com.zackeus.xupdate.entity.UpdateEntity;
import com.zackeus.xupdate.entity.UpdateError;
import com.zackeus.xupdate.factory.IUpdateDownloader;
import com.zackeus.xupdate.listener.OnFileDownloadListener;

import java.io.File;

/**
 * 版本更新提示器基类
 * @name: BaseUpdateActivity
 * @author: zz
 * @date: 2022/12/8
 */
public abstract class BaseUpdateActivity<D extends IUpdateDownloader> extends AppCompatActivity {

    public final static String KEY_UPDATE_ENTITY = "key_update_entity";
    public final static String KEY_UPDATE_PROMPT_ENTITY = "key_update_prompt_entity";

    protected final static int REQUEST_CODE_REQUEST_PERMISSIONS = 111;

    private final Handler mMainHandler = new Handler(Looper.getMainLooper());

    /* 更新信息 */
    protected LibraryUpdateEntity updateEntity;
    /* 提示器参数信息 */
    protected LibraryPromptEntity promptEntity;

    /* 下载器 */
    protected D downLoader;

    private XUpdateService.XUpdateBinder mBinder;

    private final ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            mBinder = (XUpdateService.XUpdateBinder) iBinder;
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {}
    };

    private final OnFileDownloadListener mDownLoaderListener = new OnFileDownloadListener() {
        @Override
        public void onStart() {
            if (Utils.isMainThread()) {
                BaseUpdateActivity.this.mBinder.onStart();
                BaseUpdateActivity.this.onDownloadStart();
            } else {
                BaseUpdateActivity.this.mMainHandler.post(() -> {
                    BaseUpdateActivity.this.mBinder.onStart();
                    BaseUpdateActivity.this.onDownloadStart();
                });
            }
        }

        @Override
        public void onProgress(long progress, long total) {
            if (Utils.isMainThread()) {
                BaseUpdateActivity.this.mBinder.onProgress(progress, total);
                BaseUpdateActivity.this.onDownloadProgress(progress, total);
            } else {
                BaseUpdateActivity.this.mMainHandler.post(() -> {
                    BaseUpdateActivity.this.mBinder.onProgress(progress, total);
                    BaseUpdateActivity.this.onDownloadProgress(progress, total);
                });
            }
        }

        @Override
        public void onCompleted(File file) {
            if (Utils.isMainThread()) {
                BaseUpdateActivity.this.mBinder.onCompleted(file);
                if (!XUpdate.with().startInstallApk(BaseUpdateActivity.this, BaseUpdateActivity.this.updateEntity)) {
                    onInstallError(new Exception("APK file Installation failed"));
                    return;
                }
                BaseUpdateActivity.this.onInstallCompleted(file);
            } else {
                BaseUpdateActivity.this.mMainHandler.post(() -> {
                    BaseUpdateActivity.this.mBinder.onCompleted(file);
                    if (!XUpdate.with().startInstallApk(BaseUpdateActivity.this, BaseUpdateActivity.this.updateEntity)) {
                        onInstallError(new Exception("APK file Installation failed"));
                        return;
                    }
                    BaseUpdateActivity.this.onInstallCompleted(file);
                });
            }
        }

        @Override
        public void onError(Throwable throwable) {
            XUpdate.with().onUpdateError(new UpdateError(Error.DOWNLOAD_FAILED, throwable));

            if (Utils.isMainThread()) {
                BaseUpdateActivity.this.mBinder.onError(throwable);
                BaseUpdateActivity.this.onInstallError(throwable);
            } else {
                BaseUpdateActivity.this.mMainHandler.post(() -> {
                    BaseUpdateActivity.this.mBinder.onError(throwable);
                    BaseUpdateActivity.this.onInstallError(throwable);
                });
            }
        }
    };

    /**
     * 初始化视图意图
     * @param intent
     * @param libraryUpdate
     * @param libraryPrompt
     */
    public static void initIntent(@NonNull final Intent intent, @NonNull LibraryUpdateEntity libraryUpdate,
                                  @NonNull LibraryPromptEntity libraryPrompt) {
        intent.putExtra(KEY_UPDATE_ENTITY, new UpdateEntity(libraryUpdate));
        intent.putExtra(KEY_UPDATE_PROMPT_ENTITY, new PromptEntity(libraryPrompt));
    }

    @CallSuper
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        /* 渲染页面参数 */
        initParam();
        setContentView(initContentView(savedInstanceState));

        Bundle bundle = getIntent().getExtras();
        this.updateEntity = bundle.getParcelable(KEY_UPDATE_ENTITY);
        this.promptEntity = bundle.getParcelable(KEY_UPDATE_PROMPT_ENTITY);
        this.downLoader = initDownLoader();
        /* 页面数据初始化 */
        initData(bundle);
    }

    @CallSuper
    @Override
    protected void onStart() {
        super.onStart();
        initWindowStyle();
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        /* 禁用返回键 */
        return keyCode == KeyEvent.KEYCODE_BACK;
    }

    @CallSuper
    @Override
    protected void onStop() {
        if (isFinishing()) {
            this.downLoader.cancelDownload();
            // TODO: 2022/11/21 设置版本更新弹窗显示状态
//            _XUpdate.setIsPrompterShow(getUrl(), false);
        }
        super.onStop();
    }

    @CallSuper
    @Override
    protected void onDestroy() {
        this.downLoader = null;
        this.mBinder = null;
        unbindService(this.conn);
        super.onDestroy();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_CODE_REQUEST_PERMISSIONS) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                /* 升级 */
                onInstallApk();
            } else {
                XUpdate.with().onUpdateError(new UpdateError(Error.DOWNLOAD_PERMISSION_DENIED));
                dismissDialog();
            }
        }
    }

    /**
     * 初始化窗口
     */
    private void initWindowStyle() {
        Window window = getWindow();
        if (window == null) {
            return;
        }

        window.setGravity(Gravity.CENTER);
        WindowManager.LayoutParams lp = window.getAttributes();
        DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
        if (this.promptEntity.getWidthRatio() > 0 && this.promptEntity.getWidthRatio() < 1) {
            lp.width = (int) (displayMetrics.widthPixels * this.promptEntity.getWidthRatio());
        }
        if (this.promptEntity.getHeightRatio() > 0 && this.promptEntity.getHeightRatio() < 1) {
            lp.height = (int) (displayMetrics.heightPixels * this.promptEntity.getHeightRatio());
        }
        window.setAttributes(lp);
    }

    /**
     * 忽略当前版本
     */
    protected final void ignoreVersion() {
        XUpdate.with().saveIgnoreVersion(updateEntity.getVersionName());
        dismissDialog();
    }

    /**
     * 关闭弹窗
     */
    @CallSuper
    protected void dismissDialog() {
        finish();
    }

    @CallSuper
    protected void initParam() {
        /* 绑定service */
        Intent intent = new Intent(this, XUpdateService.class);
        intent.setType(this.getPackageName());
        bindService(intent, conn, BIND_AUTO_CREATE);
    }

    /**
     * 初始化根布局
     * @return 布局layout的id
     */
    @LayoutRes
    protected abstract int initContentView(Bundle savedInstanceState);

    /**
     * 初始化下载器
     * @return
     */
    protected abstract D initDownLoader();

    protected void initData(Bundle bundle) {}

    //**************************** APK 安装 START ***************************//

    /**
     * 开始安装APK
     */
    protected final void installApp() {
        /* 权限判断是否有访问外部存储空间权限 */
        int flag = ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
        if (!FileUtils.isPrivatePath(updateEntity.getFileDir()) && flag != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE_REQUEST_PERMISSIONS);
        } else {
            onInstallApk();
        }
    }

    /**
     * APP安装实现方法
     */
    private void onInstallApk() {
        File file = new File(updateEntity.getFileDir(), updateEntity.getFileName());
        if (FileUtils.isFileExists(file) && XUpdate.with().encryptor().isFileValid(updateEntity)) {
            /* 文件已下载完且有效 */
            /* 如果文件加密校验值为空 有可能文件没下载完第二次直接执行此方法 */
            XLog.d("The APK file has been downloaded and started installation.");

            if (!XUpdate.with().startInstallApk(this, updateEntity)) {
                onInstallError(new Exception("APK file Installation failed"));
                return;
            }
            onInstallCompleted(file);
        } else {
            /* 文件下载 */
            this.downLoader.startDownload(updateEntity, mDownLoaderListener);
        }
    }

    /**
     * APK 下载前
     */
    protected void onDownloadStart() {}

    /**
     * APK 下载进度
     */
    protected void onDownloadProgress(long progress, long total) {}

    /**
     * APK 安装完毕
     */
    protected void onInstallCompleted(File file) {
        if (!isFinishing()) {
            dismissDialog();
        }
    }

    protected void onInstallError(Throwable throwable) {}

    //**************************** APK 安装 END ***************************//
}
